/**
 *
 *@author ZhouLan
 *@version 1.1.0
 */

/*
 * Communication类在uiAbility创建时就要挂载到全局变量globalThis上
 * 主要用来接收服务器发送的socket信息
 * */
import ArrayList from '@ohos.util.ArrayList'
import webSocket from '@ohos.net.webSocket';
import HashMap from '@ohos.util.HashMap';
import {FileUtil} from '../io/Util'

export class ListFormat{
  //将map转换成list后的格式
  id:string
  session:Session
  constructor(id:string,session:Session) {
    this.id = id
    this.session = session
  }
  static  map2Array(sessionMap:HashMap<string,Session>):Array<ListFormat>{
    let array = new Array<ListFormat>()
    let iterator = sessionMap.keys();
    for (let key of iterator) {
      array.push(new ListFormat(key,sessionMap.get(key)))
    }
    return array
  }
  static  array2Map(sessions:Array<ListFormat>){
    let map = new HashMap<string,Session>()
    for (let i = 0; i < sessions.length; i++) {
      map.set(sessions[i].id,sessions[i].session)
    }
    return map
  }
  static array2File(sessions:Array<ListFormat>){
    //sessions转换成的json字符串
    let str = JSON.stringify(sessions)
    let num = FileUtil.setMessageToFile(globalThis.context,sessions)
    //写入文件，参考java的字节流
    console.log(num+"字符")
  }
  static file2Array(){
    //读取文件中保存的json字符串
    //读取文件，参考java的字节流
    //将其转换为json对象
    let json = FileUtil.getMessageFromFile(globalThis.context)
    console.log("json:"+JSON.stringify(json));
    return json
  }
  static file2Map(){
    return this.array2Map(this.file2Array())
  }
  static map2File(sessionMap:HashMap<string,Session>){
    this.array2File(this.map2Array(sessionMap))
  }
  toString(){
    return JSON.stringify(this)
  }
}
export class Communications{
  //通信类，全局变量中的通信，用于显示，可以转换成json写入文件
  //该类的实例将会被挂载到globalThis全局变量上
  //注意：communication构造的时候需要先将globalThis.context初始化
  unread:number
  sessionMap:HashMap<string,Session>
  //存储session的map，
  deliveryStatus:ArrayList<DeliveryStatus>
  constructor() {
    //创建时应该自动读取文件，创建此实例
    this.deliveryStatus = new ArrayList<DeliveryStatus>()
    this.loadMessages()
    this.unread = 0
  }
  //当收到一条信息时，需要调用这个函数将其保存到当前对象
  setMessage(wsMessage:WsMessage){
    console.log(this.sessionMap.length+'')
    //如果当前会话不存在，创建一个会话
    if(!(this.isExist(wsMessage.fromId))){
      this.addSession(wsMessage.fromId)
    }
    this.sessionMap.get(wsMessage.fromId).messages.push(new SessionMessage(wsMessage))
    console.log(this.sessionMap.length+'')
    console.log(this.sessionMap.length+'')
  }
  //当用户发送一条信息时，需要调用此函数将信息保存到当前对象
  sendMessage(wsMessage:WsMessage){
    console.log(this.sessionMap.get(wsMessage.toId).messages[0].message)
    this.sessionMap.get(wsMessage.toId).messages.push(new SessionMessage(wsMessage))
    console.log(this.sessionMap.get(wsMessage.toId).messages.length+'')
  }
  saveMessages(){
    ListFormat.map2File(this.sessionMap)
    //将map储存到文件
    //在app挂到后台和关闭时将会执行这个函数
  }
  private loadMessages(){
    this.sessionMap = ListFormat.file2Map()
    //将文件中的json读取并赋值到当前实例的map属性
  }
  getSessionKeys(){
    return this.sessionMap.keys();
  }
  getMessagesByKey(key:string){
    return this.sessionMap.get(key).messages
  }
  isExist(key:string){
    return this.sessionMap.hasKey(key)
  }
  //如果不存在对应的会话，添加一个新的会话到sessionMap
  addSession(key:string,){
    this.sessionMap.set(key,new Session(key,new Array<SessionMessage>()))
    console.log(this.sessionMap.keys().next().value)
  }
  //添加一条新的message到session对象
  addMessage(key:string,message:SessionMessage){
    this.sessionMap.get(key).messages.push(message)
  }
  getMessageList():Array<MessageListItem>{
    console.log("获取list")
    //这个函数返回MessageList页面的渲染数据
    let arr = []
    let keys:IterableIterator<string> = this.sessionMap.keys()
    let res = keys.next()
    while (!res.done){
      let key = res.value
      let lastIndex = this.sessionMap.get(key).messages.length-1
      arr.push(new MessageListItem(key,this.sessionMap.get(key).messages[lastIndex]))
      console.log("获取list:"+key)
      console.log("获取list_value:"+this.sessionMap.get(key).messages[lastIndex].message)
      res = keys.next()
    }
    return arr
  }
  //此方法用于用户发送信息时通过对方id获取message数组，可能要弃用
  getMessagesByOppositeId(oppositeId:string):SessionMessage[]{
    if(this.sessionMap.hasKey(oppositeId)){
      return this.sessionMap.get(oppositeId).messages
    }else {
      this.addSession(oppositeId)
      return this.sessionMap.get(oppositeId).messages
    }
  }
  //新的方式，通过opposite获取对应的session,便于
  getSessionByOppositeId(opposite:string):Session{
    if(this.sessionMap.hasKey(opposite)){
      return this.sessionMap.get(opposite)
    }else {
      this.addSession(opposite)
      return this.sessionMap.get(opposite)
    }
  }

}
export class MessageListItem{
  //规范messageList的格式
  key:string
  value:SessionMessage
  constructor(key:string,value:SessionMessage) {
    this.key = key
    this.value = value
  }
}
export class Message{
  //Message父类
  //ws发送的与本地存储的message对象的相同属性
  message:string
  timeStamp:number
}
export class SessionMessage extends Message{
  //实际存储在会话中的对象，只用来显示
  isMe:boolean//是否是本人收到的信息
  constructor(wsMsg:WsMessage|undefined,isMe?:boolean,message?:string,timeStamp?:number) {
    super();
    if(wsMsg){
      this.message = wsMsg.message
      this.timeStamp = wsMsg.timeStamp
      if(wsMsg.toId==globalThis.applicationConfig.admin){
        this.isMe = true
      }else {
        this.isMe = false
      }
    }else {
      this.message = message
      this.isMe = isMe
      this.timeStamp = timeStamp
    }
  }
}
export class WsMessage extends Message{
  //参与发送的message对象
  fromId:string//发送方
  toId:string//自己
  type:number
  //此对象是否要设置构造函数，如何设置，需要考虑
  //需要，当当前用户向外发送信息时，需要构造器
  constructor(fromId:string|undefined,toId:string|undefined,type:number|undefined,message:string|undefined,timeStamp:number|undefined) {
    super();
    this.fromId = fromId
    this.toId = toId
    this.type = type
    this.message = message
    this.timeStamp = timeStamp
    //当商家收到用户的订单以后，对商家进行提醒，
  }
}
export class DeliveryStatus{
  //配送状态类
  type:number
  goodsId:string
  startTime:number//发起时间(时间戳)
  statusCode:number//状态码，规定状态0为未接单，1为已接单，2为发送中，3为已送达
}
export class Order{
  //用户提交的单个订单类
  goodsId:string//商品id
  num:number//商品数
  userId:string//用户id
  type:number
  startTime:number//发起时间(时间戳)
  orderState:number//订单状态，0为已发起，1为商家已接收，2为已发货，3为已送达
  orderNo:number//订单编号
}
//ws接收到的信息需要存储到本地文件，并追加在信息显示的数据中，信息显示数据为一个map,key值为发送
//对象的id号，存储一个会话对象。map对象方便找到对应的会话对象并增加值。但是有一个问题，就是每次修改
//都需要替换value，会造成资源浪费，但是用数组存储却不方便找到对应的会话对象
//先定义好会话对象的数据结构，旨在方便查询以及方便取用修改，可以定义成对象中的数组，操作数组即可
export class Session{
  //会话对象
  visible:boolean//是否可见
  messages:Array<SessionMessage>
  key:string//发送对象的id
  getKey(){
    return this.key
  }
  isVisible(){
    return this.visible
  }
  visibleNegate(){
    //visible取反
    this.visible = !this.visible
  }
  constructor(key:string,messages:Array<SessionMessage>) {
    this.key = key
    this.messages = messages
    this.visible = true
  }
  addMessage(message:SessionMessage){
    this.messages.push(message)
  }
  getMessages(){
    return this.messages
  }

}


// export function createWs(){
//   console.log("wsUrl:"+globalThis.applicationConfig.wsBaseUrl)
//   let ws = webSocket.createWebSocket()
//   ws.connect(globalThis.applicationConfig.wsBaseUrl+'/chat/'+globalThis.applicationConfig.admin)
//   ws.on('open',(err,value)=>{
//     if(err){
//       console.error(err.message)
//       return
//     }
//     globalThis.applicationConfig.ws = ws
//     console.log("ws连接已打开")
//   })
//   ws.on('message',(err,value)=>{
//     if(err){
//       console.error(err.message)
//       return
//     }
//     console.log("收到的信息:"+value)
//     console.log("收到的信息:"+typeof (JSON.parse(value.toString()).type));
//     //判断收到的信息类型，一共有三种：0：普通信息，1：用户提交信息，2：商家发送的状态信息
//     let wsMessage:WsMessage = JSON.parse(value.toString())
//     if(wsMessage.type){
//       //如果不是0
//       globalThis.communications.deliveryStatus.push(wsMessage)
//     }else {
//       globalThis.communications.setMessage(wsMessage)
//     }
//   })
//   ws.on('close',()=>{
//     //如果关闭则重连
//     this.createWs();
//   })
// }